package com.github.llyb120.compiler.java;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.io.resource.ClassPathResource;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.lang.func.Func1;
import cn.hutool.core.util.ClassLoaderUtil;
import cn.hutool.core.util.StrUtil;
import javassist.*;
import lombok.SneakyThrows;

import java.io.InputStream;
import java.net.URLClassLoader;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.regex.Matcher;

/**
 * @Author: Administrator
 * @Date: 7/27/2021 4:41 PM
 */
public class JavassistCompiler {
    static Snowflake snowflake = new Snowflake(0L, 0L);

    public static CompileResult compile(DynamicCode code) {
        String className = String.format("dy_%d", snowflake.nextId());
        code.setClassName(className);
        return CompileResult.builder()
            .name("com.github.llyb120.dynamic.clz." + className)
            .sourceCode(code.getMainCode())
            .build();
    }

    @SneakyThrows
    public static BaseDynamicJavaCode run(DynamicCode code){
        CompileResult compileResult = JavassistCompiler.compile(code);
        ClassPool pool = ClassPool.getDefault();
        CtClass ctClass = pool.makeClass(compileResult.getName());
//        ctClass.setSuperclass(pool.get("com.github.llyb120.compiler.java.BaseDynamicJavaCode"));
        ctClass.setSuperclass(pool.get(BaseDynamicJavaCode.class.getName()));
        CtMethod method = CtNewMethod.make(String.format("public void run() throws Exception{ %s }", compileResult.getSourceCode()), ctClass);
        ctClass.addMethod(method);
        byte[] bs = ctClass.toBytecode();
        compileResult.setByteCode(bs);
//        Class clz = ctClass.toClass(loader);
        Class clz = new DynamicJavaLoader(compileResult).loadClass(compileResult.getName());
        BaseDynamicJavaCode ins = (BaseDynamicJavaCode) clz.newInstance();
        ins.run();
        return ins;
    }
}
